#ifndef BASE_WINDOW_H_
#define BASE_WINDOW_H_

#include "stringencode.h"

// Define platform specific window types.
#if defined(LINUX)
typedef unsigned long Window;  // Avoid include <X11/Xlib.h>.
#elif defined(WIN32)
// We commonly include win32.h in talk/base so just include it here.
#include "win32.h"  // Include HWND, HMONITOR.
#elif defined(OSX)
typedef unsigned int CGWindowID;
typedef unsigned int CGDirectDisplayID;
#endif

namespace base {

	class WindowId {
	public:
		// Define WindowT for each platform.
#if defined(LINUX)
		typedef Window WindowT;
#elif defined(WIN32)
		typedef HWND WindowT;
#elif defined(OSX)
		typedef CGWindowID WindowT;
#else
		typedef unsigned int WindowT;
#endif

		static WindowId Cast(uint64 id) {
#if defined(WIN32)
			return WindowId(reinterpret_cast<WindowId::WindowT>(id));
#else
			return WindowId(static_cast<WindowId::WindowT>(id));
#endif
		}

		static uint64 Format(const WindowT& id) {
#if defined(WIN32)
			return static_cast<uint64>(reinterpret_cast<uintptr_t>(id));
#else
			return static_cast<uint64>(id);
#endif
		}

		WindowId() : id_(0) {}
		WindowId(const WindowT& id) : id_(id) {}  // NOLINT
		const WindowT& id() const { return id_; }
		bool IsValid() const { return id_ != 0; }
		bool Equals(const WindowId& other) const {
			return id_ == other.id();
		}

	private:
		WindowT id_;
	};

	class DesktopId {
	public:
		// Define DesktopT for each platform.
#if defined(LINUX)
		typedef Window DesktopT;
#elif defined(WIN32)
		typedef HMONITOR DesktopT;
#elif defined(OSX)
		typedef CGDirectDisplayID DesktopT;
#else
		typedef unsigned int DesktopT;
#endif

		static DesktopId Cast(int id, int index) {
#if defined(WIN32)
			return DesktopId(reinterpret_cast<DesktopId::DesktopT>(id), index);
#else
			return DesktopId(static_cast<DesktopId::DesktopT>(id), index);
#endif
		}

		DesktopId() : id_(0), index_(-1) {}
		DesktopId(const DesktopT& id, int index)  // NOLINT
			: id_(id), index_(index) {
		}
		const DesktopT& id() const { return id_; }
		int index() const { return index_; }
		bool IsValid() const { return index_ != -1; }
		bool Equals(const DesktopId& other) const {
			return id_ == other.id() && index_ == other.index();
		}

	private:
		// Id is the platform specific desktop identifier.
		DesktopT id_;
		// Index is the desktop index as enumerated by each platform.
		// Desktop capturer typically takes the index instead of id.
		int index_;
	};

	// Window event types.
	enum WindowEvent {
		WE_RESIZE = 0,
		WE_CLOSE = 1,
		WE_MINIMIZE = 2,
		WE_RESTORE = 3,
	};

	inline std::string ToString(const WindowId& window) {
		return ToString(window.id());
	}

}  // namespace base

#endif  // BASE_WINDOW_H_
